package main

import "fmt"

func sumFn(x int, y int) int {
	return x + y
}

func subFn(x int, y int) int {
	return x - y
}

// 参数简写, 参数类型相同时
func subFn1(x, y int) int {
	return x - y
}

// 函数的可变参数,可变参数是指函数的参数数量不固定,
// go语言中的可变参数通过在参数名后加...来实现
func sumFn1(x ...int) int {
	sum := 0
	for _, v := range x {
		sum += v
	}
	return sum
}

func sumFn2(x int, y ...int) int {
	sum := x
	for _, v := range y {
		sum += v
	}
	return sum
}

// 多个返回值
func sumFn3(x int, y int) (int, int) {
	return x + y, x - y
}

// 返回值命名法
func sumFn4(x int, y int) (sum int, sub int) {
	sum = x + y
	sub = x - y
	return
}

func sumFn5(x, y int) (sum, sub int) {
	sum = x + y
	sub = x - y
	return
}

// 定义一个函数类型
type calc func(int, int) int

func add(x, y int) int {
	return x + y
}

func sub(x, y int) int {
	return x - y
}

// 自定义类型
type myInt int

// 函数作为另一个函数的参数
func calcFunc(x, y int, cb func(int, int) int) int {
	return cb(x, y)
}

func calcFunc2(x, y int, cb calc) int {
	return cb(x, y)
}

// 定义方法类型
type calcType func(int, int) int

// 函数作为返回值
func doCalc(o string) calcType {
	switch o {
	case "+":
		return add
	case "-":
		return func(x int, y int) int {
			return x - y
		}
	case "*":
		return func(x int, y int) int {
			return x * y
		}
	default:
		return nil
	}
}

// 递归调用
func fn1(x int) int {
	if x <= 1 {
		return 1
	}
	return x + fn1(x-1)
}

func fn2(x int) int {
	if x <= 1 {
		return 1
	}
	return x * fn2(x-1)
}

// 闭包
func adder() func() int {
	var i = 10
	return func() int {
		return i + 1
	}
}

func adder2() func(int) int {
	var i = 10
	return func(y int) int {
		i += y
		return i
	}
}

func main() {
	//sum := sumFn(22, 2)
	//fmt.Println(sum)
	//
	//sub := subFn(222, 22)
	//fmt.Println(sub)
	//
	//sub2 := subFn1(222, 22)
	//fmt.Println(sub2)
	//
	//sum2 := sumFn1(1, 2, 3, 4, 5)
	//fmt.Println(sum2)
	//
	//sum3 := sumFn2(1, 2, 3, 4, 5)
	//fmt.Println(sum3)
	//
	//sum4, sub4 := sumFn3(5, 2)
	//fmt.Println(sum4, sub4)
	//
	//sum5, sub5 := sumFn4(55, 22)
	//fmt.Println(sum5, sub5)
	//
	//sumFn(1, 2)
	//
	//var slice []string
	//slice = append(slice, "aa")
	//slice = append(slice, "cc")
	//slice = append(slice, "bb")
	//fmt.Println(slice)
	//sort.Strings(slice)
	//fmt.Println(slice)

	// 全局变量: 定义在方法外部
	// 局部变量: 定义在方法内部

	//var c calc
	//c = add
	//// main.calc
	//fmt.Printf("c的类型: %T\n", c)
	//fmt.Println(c(1, 2))
	//
	//var f = add
	//// func(int, int) int
	//fmt.Printf("f的类型: %T\n", f)
	//fmt.Println(f(1, 2))

	//sum := calcFunc(1, 2, sub)
	//fmt.Println(sum)

	//j := calcFunc(3, 4, func(x int, y int) int {
	//	return x * y
	//})
	//fmt.Println(j)

	//calc := doCalc("+")
	//fmt.Println(calc(1, 2))

	// 匿名函数, 自执行函数
	//func() {
	//	fmt.Println("匿名函数")
	//}()
	//var add = func(x, y int) int {
	//	return x + y
	//}
	//fmt.Println(add(12, 12))

	// 递归调用
	//fmt.Println(fn1(100))
	//fmt.Println(fn2(5))

	// 闭包
	var fn = adder2()
	fmt.Println(fn(11))
	fmt.Println(fn(11))
	fmt.Println(fn(11))
}
